
//**************************************************************************/
// Copyright (c) 2010 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: August 2010
//**************************************************************************/

#if defined(JAMBUILD)
#include <Mudbox/mudbox.h>
#include <MapExtractor/MapExtractorInterface.h>
#else
#include "../../include/Mudbox/mudbox.h"
#include "../../include/MapExtractor/MapExtractorInterface.h"
#endif
#include "PtexLayout.h"
#include "ptex/Ptexture.h"

using namespace mudbox;

// This class is responsible to utilize the result of the map extraction for each reference points. In case of a ptex exraction, this means writing the data into a ptex file.
// There will be a separated instance of this class during the extraction process for each enabled component (one for displacement, one for ambient occlusion etc..).
// The main function in this class must be thread safe, which makes the things a bit more complicated. The extraction process uses multiple threads.
class PtexUtilizer : public Utilizer
{
	// The following structure holds data for a single base level face.
	struct FaceData
	{
		FaceData( unsigned int iWidth, unsigned int iHeight );
		QVector<float> m_aData;
		unsigned int m_iSamplesLeft;
		unsigned int m_iWidth;
		unsigned int m_iHeight;
	};

	DECLARE_CLASS;

	enum Format
	{
		eFormat8bitInteger,
		eFormat16bitInteger,
		eFormat16bitFloat,
		eFormat32bitFloat
	};
	PtexUtilizer( void );
	// This function retuns the list of the supported file extensions by this class (which is simply *.ptx).
	virtual QStringList SupportedExtensions( Component * ) const;
	// This function lets the class decide which type of layout it wants to use. In this case we use out own layout class, PtexLayout.
	virtual Layout *CreateLayout( void ) { return new PtexLayout; };
	// This is the main function, this is called by the framework once for each reference point. This function must be thread safe.
	virtual void StoreData( const Data &cData, const TargetLocation &cTarget, bool bHit );
	// This function lets the class respond to some special events.
	virtual void OnPhaseEvent( PhaseEventType );
	// When the map extraction node is stored in a mud file, this function must seriaize the state of the object. This is never called during a map extraction operation.
	virtual void Serialize( Stream & );
	// Set the format of the file written.
	inline void SetFormat( Format eFormat ) { m_eFormat = eFormat; };
	// In this function we store the address of the layout object to be accessed it in the future.
	virtual void Initialize( Layout *, Component * );
	// This function writes the metadata for the mesh to an open ptex file.
	static void WriteMeshData( PtexWriter *pWriter, const Mesh *pMesh );
private:
	
	// This function creates and opens a new ptx file for the given mesh.
	void OpenFile( const Mesh *pMesh );
	// This function closes the lastly opened ptx file.
	void CloseFile( void );	

	// The mesh which is currently being processed.
	const Mesh *m_pMesh;
	// The PtexWriter object which is being used for the current mesh.
	class PtexWriter *m_pWriter;
	// Number of faces written to the ptex file.
	unsigned int m_iPtexFaceCount;
	// Array of the faces in the current mesh.
	QVector<FaceData *> m_aFaces;
	// Number of components which must be written to the file for each pixel. At this moment this is always three.
	int m_iComponentCount;
	// Format of the data.
	aenum m_eFormat;
	// This attribute controls if the mesh topology data should be written to the file or not. This should always be true, added mainly for demonstration purposes.
	//abool m_bIncludeMeshData;
	// Number of faces processed.
	unsigned int m_iFacesProcessed;
	// Pointer to the current layout, this is used only when the target mesh is nsided.
	const PtexLayout *m_pLayout;
};

